﻿// -------------------------------------------------------------------------
//    @FileName         :    NFCityNpcLevelExt.cpp
//    @Author           :    Gao.Yi
//    @Date             :    2025-09-29
//    @Email			:    445267987@qq.com
//    @Module           :    NFCityNpcLevelExt
//    @Desc             :
//
// -------------------------------------------------------------------------

#include "NFCityNpcLevelExt.h"

#include "NFCityNpc.h"
#include "DescStore/FunctionNpcDesc.h"
#include "DescStore/TriggerNpcDesc.h"
#include "NFCityWorldObject.h"
#include "NFCityPlayer.h"

NFCityNpcLevelExt::NFCityNpcLevelExt()
{
    if (EN_OBJ_MODE_INIT == NFShmMgr::Instance()->GetCreateMode())
    {
        CreateInit();
    }
    else
    {
        ResumeInit();
    }
}

NFCityNpcLevelExt::~NFCityNpcLevelExt()
{
}

int NFCityNpcLevelExt::CreateInit()
{
    return 0;
}

int NFCityNpcLevelExt::ResumeInit()
{
    return 0;
}

int NFCityNpcLevelExt::Init(NFCityNpc* pNpc)
{
    CHECK_NULL(0, pNpc);
    auto pNpcDesc = FunctionNpcDesc::Instance()->GetDesc(pNpc->GetNpcID());
    CHECK_NULL(0, pNpcDesc);

    for (int i = 0; i < pNpcDesc->function.size(); ++i)
    {
        if (pNpcDesc->function[i].type == proto_ff::EN_FUNCTION_NPC_TYPE_TRIGGER_BATTLE)
        {
            auto pTriggerNpcDesc = TriggerNpcDesc::Instance()->GetDesc(pNpcDesc->function[i].id);
            CHECK_NULL(0, pTriggerNpcDesc);

            if (IsLevelFull())
            {
                break;
            }
            NFCityNpcLevelInfo info;
            info.m_iTriggerNpcId = pNpcDesc->function[i].id;
            info.m_bInTrigger = false;
            info.m_iTriggerTime = 0;
            info.m_iTriggerCnt = 0;
            m_astLevelInfo.push_back(info);
        }
    }

    return 0;
}

bool NFCityNpcLevelExt::IsVisibleByQuest(int iQuestId)
{
    for (int i = 0; i < m_astLevelInfo.size(); ++i)
    {
        auto pTriggerNpcDesc = TriggerNpcDesc::Instance()->GetDesc(m_astLevelInfo[i].m_iTriggerNpcId);
        CHECK_NULL_RE_FALSE_WF(0, pTriggerNpcDesc, "no desc:{}", m_astLevelInfo[i].m_iTriggerNpcId);

        if (pTriggerNpcDesc->task_id == iQuestId)
        {
            return true;
        }
    }

    return false;
}

bool NFCityNpcLevelExt::IsHideVisible(NFCityWorldObject* pAcceptWo)
{
    if (!pAcceptWo->IsPlayer())
    {
        return false;
    }

    auto pPlayer = dynamic_cast<NFCityPlayer*>(pAcceptWo);
    CHECK_NULL_RE_FALSE(0, pPlayer);
    for (int i = 0; i < m_astLevelInfo.size(); ++i)
    {
        auto pTriggerNpcDesc = TriggerNpcDesc::Instance()->GetDesc(m_astLevelInfo[i].m_iTriggerNpcId);
        CHECK_NULL_RE_FALSE_WF(0, pTriggerNpcDesc, "no desc:{}", m_astLevelInfo[i].m_iTriggerNpcId);

        if (pTriggerNpcDesc->task_id > 0 && pPlayer->HasNonFinishTask(pTriggerNpcDesc->task_id))
        {
            return true;
        }
    }

    return false;
}

int NFCityNpcLevelExt::CheckTriggerLevel(NFCityPlayer* pPlayer, int iLevelId)
{
    NFCityNpcLevelInfo* pLevelInfo = FindLevelInfo(iLevelId);
    CHECK_NULL_RET_VAL_WF(0, pLevelInfo, ERR_CODE_NPC_CANNOT_TRIGGER_LEVEL, "FindLevelInfo failed, iLevel:{}", iLevelId);

    auto pTriggerNpcDesc = TriggerNpcDesc::Instance()->GetDesc(pLevelInfo->m_iTriggerNpcId);
    CHECK_NULL(0, pTriggerNpcDesc);

    if (pTriggerNpcDesc->only_trigger && pLevelInfo->m_bInTrigger)
    {
        return proto_ff::ERR_CODE_NPC_IS_IN_TRIGGER;
    }

    if (pTriggerNpcDesc->trigger_num > 0 && pLevelInfo->m_iTriggerCnt >= pTriggerNpcDesc->trigger_num)
    {
        return proto_ff::ERR_CODE_NPC_TRIGGER_CNT_EMPTY;
    }

    if (pTriggerNpcDesc->need_taskid > 0)
    {
        if (!pPlayer->HasTask(pTriggerNpcDesc->need_taskid))
        {
            return proto_ff::ERR_CODE_NPC_TRIGGER_LEVEL_NEED_QUEST;
        }
    }

    return 0;
}

int NFCityNpcLevelExt::OnTriggerLevel(NFCityNpc* pNpc, int iLevelId)
{
    CHECK_NULL(0, pNpc);
    NFCityNpcLevelInfo* pLevelInfo = FindLevelInfo(iLevelId);
    CHECK_NULL_WF(0, pLevelInfo, "FindLevelInfo failed, iLevel:{}", iLevelId);

    pLevelInfo->m_bInTrigger = true;
    pLevelInfo->m_iTriggerTime = NF_ADJUST_TIMENOW();
    pLevelInfo->m_iTriggerCnt++;

    auto pTriggerNpcDesc = TriggerNpcDesc::Instance()->GetDesc(pLevelInfo->m_iTriggerNpcId);
    CHECK_NULL(0, pTriggerNpcDesc);

    if (pTriggerNpcDesc->trigger_num > 0 && pLevelInfo->m_iTriggerCnt >= pTriggerNpcDesc->trigger_num)
    {
        pNpc->SetRemove();
    }

    LOG_DEBUG(0, "npc:{} trigger level:{} cnt:{}", pNpc->GetGlobalId(), iLevelId, pLevelInfo->m_iTriggerCnt);

    return 0;
}

int NFCityNpcLevelExt::OnBattleEnd(NFCityNpc* pNpc, int iLevelId, bool bIsWin)
{
    CHECK_NULL(0, pNpc);
    NFCityNpcLevelInfo* pLevelInfo = FindLevelInfo(iLevelId);
    CHECK_NULL_WF(0, pLevelInfo, "FindLevelInfo failed, iLevel:{}", iLevelId);

    pLevelInfo->m_bInTrigger = false;

    auto pTriggerNpcDesc = TriggerNpcDesc::Instance()->GetDesc(pLevelInfo->m_iTriggerNpcId);
    CHECK_NULL(0, pTriggerNpcDesc);

    if (bIsWin && pTriggerNpcDesc->victory_destroy)
    {
        pNpc->SetRemove();
    }

    return 0;
}

NFCityNpcLevelInfo* NFCityNpcLevelExt::FindLevelInfo(int iLevelId)
{
    for (int i = 0; i < m_astLevelInfo.size(); ++i)
    {
        auto pTriggerNpcDesc = TriggerNpcDesc::Instance()->GetDesc(m_astLevelInfo[i].m_iTriggerNpcId);
        CHECK_NULL_RE_NULL(0, pTriggerNpcDesc, "no desc:{}", m_astLevelInfo[i].m_iTriggerNpcId);

        for (int k = 0; k < pTriggerNpcDesc->relative_level.size(); ++k)
        {
            if (pTriggerNpcDesc->relative_level[k] == iLevelId)
            {
                return &m_astLevelInfo[i];
            }
        }
    }

    return nullptr;
}
